﻿using System;
using System.Collections.Generic;
using System.Drawing;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using OpenTK.Input;

namespace Chimp.Core
{
    public class RegisterStuff
    {
        public virtual void RegAll()
        {
            
        }
    }
    public class ChimpApp : GameWindow
    {
        public static ChimpRenderTarget FrameBufferTarget;
        public static ChimpTexture2D FrameBuffer;
        public static ChimpTextureDepth FrameDepth;
        public static ChimpApp Cur;
        public static double FrameTime;
        public static float W, H;
        public static List<ChimpState> ActiveState = new List<ChimpState>();
        private static string DelayState = "";
        public static Vector2 Mid;
        private int Fps;
        private int Frame;
        private int NextTick;
        public static Dictionary<string, ChimpState> States = new Dictionary<string, ChimpState>();
        public static List<ChimpTransient> TList = new List<ChimpTransient>();
        /// <summary>Creates a 800x600 window with the specified title.</summary>
        public ChimpApp()

            : base(800, 600, GraphicsMode.Default, "OpenTK Quick Start Sample")
        {
            VSync = VSyncMode.Off;
            W = 800;
            H = 600;
            ResetEngine();
        }
        public static void BeginTransient(ChimpTransient t)
        {
            TList.Add(t);
        }
        public ChimpApp(int width, int height, string title, bool full)
            : base(
                width, height, GraphicsMode.Default, title, full ? GameWindowFlags.Fullscreen : GameWindowFlags.Default)
        {
            VSync = VSyncMode.Off;
            W = width;
            H = height;
            ResetEngine();
        }

        public List<ChimpScreenFilter> Filters { get; set; }

        public static ChimpState CurState
        {
            get
            {
                if (ActiveState.Count == 0) return null;
                return ActiveState[ActiveState.Count - 1];
            }
        }
        public static void RegState(string id,ChimpState s)
        {
            CheckState(id);
            States.Add(id, s);
        }

        public static void CheckState(string id)
        {
            if(States.ContainsKey(id))
            {
                if(CurState == States[id])
                {
                    PopState();
                }
                States.Remove(id);
            }
        }

        public static void RegState(ChimpState s, string id)
        {
            CheckState(id);
            States.Add(id, s);
        }

        public static void PushStateDelayed(string id)
        {
            DelayState = id;
        }

        public static void PushState(string id)
        {
            Console.WriteLine("Pushing:"+id);
            if (ActiveState.Count != 0)
            {
                ActiveState[ActiveState.Count - 1].OnPause();
            }
            ChimpState s = States[id];
            ActiveState.Add(s);
            ChimpUI.Push[0] = null;
            ChimpUI.Over = null;
            ChimpUI.UIRoot = null;
            s.OnStart();
        }

        public static void PopState()
        {
            if (ActiveState.Count == 0)
            {
                return;
            }

            CurState.OnStop();
            ActiveState.Remove(CurState);
            if (CurState != null)
            {
                CurState.OnResume();
            }
        }

        public static bool initonce = false;

        public void ResetEngine()
        {
            Cur = this;
            // XenoCore.CurrentApp = this;
            // XenoCore.CurrentScene = new XenoGraph();
            // XenoCore.CurrentView = XenoFactory.Node.Camera("View Camera", XenoCore.CurrentScene.RootNode);
            ResetGL();
        }

        public static void ResetGL()
        {
            ChimpI.Init();
            ChimpText.Init();

//            Filters = new List<ChimpScreenFilter>();
            GL.ClearColor(Color.Black);
            if(!initonce)
                ChimpJob.InitJobSystem();
            // System.Windows.Forms.Cursor.Current = System.Windows.Forms.Cursors.Arrow;
            Mid = new Vector2(W/2, H/2);

            ChimpUI.InitUI ( );
            ChimpDraw.InitChimpDraw ( );

            initonce = true;
            GL.ClearColor ( Color.Black );
            GL.Enable ( EnableCap.DepthTest );
            DoInit ( );
        }

        public ChimpScreenFilter AddFilter(ChimpScreenFilter f)
        {
            Filters.Add(f);
            return f;
        }

        /// <summary>Load resources here.</summary>
        /// <param name="e">Not used.</param>
        protected override void OnLoad(EventArgs e)
        {
            GL.ClearColor(Color.Black);
            GL.Enable(EnableCap.DepthTest);
            DoInit();
        }

        // public XenoNode RootNode()
        //{
        //   return XenoCore.CurrentScene.RootNode;
        //}

        public static void DoInit()
        {
            DoGL();
        }

        public virtual void DoUpdate()
        {
        }

        public virtual void DoPreRender()
        {
        }

        public virtual void DoPostRender()
        {
        }

        protected override void OnResize(EventArgs e)
        {
            DoGL();
        }

        public static void DoGL()
        {
            GL.Viewport(new Rectangle(0, 0, (int) W, (int) H));

            // Matrix4 projection = Matrix4.Perspective((float)Math.PI / 4, Width / (float)Height, 1.0f, 64.0f);
            // GL.MatrixMode(MatrixMode.Projection);
            //GL.LoadMatrix(ref projection);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();

            Matrix4 projectionMatrix = Matrix4.CreateOrthographicOffCenter(0, W,
                                                                           H, 0, -1.0f, 1.0f);

            GL.LoadMatrix(ref projectionMatrix);
            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();


            //GL.Disable(EnableCap.Blend);
            //GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
            //GL.Disable(EnableCap.AlphaTest);

            GL.DepthMask(false);
            GL.Disable(EnableCap.DepthTest);
        }

        /// <summary>
        /// Called when your window is resized. Set your viewport here. It is also
        /// a good place to set up your projection matrix (which probably changes
        /// along when the aspect ratio of your window).
        /// </summary>
        /// <param name="e">Contains information on the new Width and Size of the GameWindow.</param>
        protected override void OnUpdateFrame(FrameEventArgs e)
        {
            if(ChimpI.IsKeyDown(Key.Escape))
            {
                this.Exit();
            }
            if (DelayState != "")
            {
                string ds = DelayState;
                DelayState = "";
                PushState(ds);
                return;
            }
            FrameTime = e.Time;

            DoUpdate();
            if (ActiveState != null)
            {
                CurState.OnUpdate();
            }
            foreach(var t in TList)
            {
                t.OnUpdate();
            }
            //    XenoCore.CurrentScene.UpdateGraph();
        }


        protected override void OnRenderFrame(FrameEventArgs e)
        {
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
            //  XenoCore.LightList = XenoCore.CurrentScene.RootNode.AllWithType(typeof(XenoMod_Light), null);

            if (Filters.Count > 0)
            {
                DoPreRender();

                ChimpTexture2D prev = null;

                foreach (ChimpScreenFilter filter in Filters)
                {
                    //filter.PerformRender(XenoCore.CurrentScene, prev);
                }

                DoPostRender();
            }
            else
            {
                DoPreRender();

                //   XenoCore.CurrentScene.RootNode.PerformRender();

                DoPostRender();
            }
            if (ActiveState != null)
            {
                CurState.OnDraw();
            }
            foreach(var t in TList)
            {
                t.OnDraw();
            }
            Frame++;
            if (Environment.TickCount > NextTick)
            {
                Fps = Frame;
                NextTick = Environment.TickCount + 1000;
                Frame = 0;
                Console.WriteLine("FPS:" + Fps);
            }
            SwapBuffers();
        }
    }
}